﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;

namespace FxCopContrib
{
    public class RefererenceLocalStructCorrectlyInClosure 
        : RuleBase
    {
        public RefererenceLocalStructCorrectlyInClosure()
            : base("RefererenceLocalStructCorrectlyInClosure")
        {}

        public override ProblemCollection Check(Member member)
        {
            Method method = member as Method;
            if (method != null)
            {
                VisitMethod(method);
            }
            return this.Problems;
        }

        public override void VisitMethod(Method method)
        {
            base.VisitMethod(method);

            if (method.Locals != null)
            {
                var localsToWatch = method.Locals.Where(l => IsPotentiallyProblematicLocal(l));
                if (localsToWatch.Any())
                {
                    this.Problems.Add(new Problem(GetResolution(), method));    
  
                    // See if the delegate is created and the value of its local(s) are changed afterwards.
                    // See that delegate is passed to an Async method or eventhandler and its value changes afterwards
                }

                

                // Ok, so we have a local that might cause issues... Let's see what we're going to do with it.

            }
        }

        public bool IsPotentiallyProblematicLocal(Local local)
        {
            return
                (local.Type.IsPrivate)
                && (local.Type.Name.Name.StartsWith("<>c__DisplayClass", StringComparison.OrdinalIgnoreCase))
                && GetPotentiallyProblematicFields(local).Any();
        }

        public IEnumerable<Field> GetPotentiallyProblematicFields(Local local)
        {
            return local.Type.Members.Where(member => member.NodeType == NodeType.Field && (((Field)member).Type.IsStructural || ((Field)member).Type.IsValueType)).Cast<Field>();
        }
    }
}
